package com.example.lf.slidemenu.customview;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.example.lf.slidemenu.utils.ColorUtil;
import com.nineoldandroids.animation.FloatEvaluator;
import com.nineoldandroids.animation.IntEvaluator;
import com.nineoldandroids.view.ViewHelper;

/**
 * slideMenu的实现
 * Created by LF on 2017-02-10.
 */

public class MySlideMenu extends FrameLayout {
    private ViewDragHelper helper;
    private View menuView;
    private View mainView;
    private int width;
    private float dragRange;//拖拽范围

    private FloatEvaluator floatEvaluator;//float的计算器
    private IntEvaluator intEvaluator;//int的计算器

    //定义状态常量
    enum DragState {
        Open, Close;
    }

    private DragState currentState = DragState.Close;//当前SlideMenu的状态默认是关闭的


    public DragState getCurrentState() {
        return currentState;
    }

    public MySlideMenu(Context context) {
        super(context);
        init();

    }

    public MySlideMenu(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public MySlideMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 2) {
            throw new IllegalArgumentException("布局只能包含两个控件");
        }
        menuView = getChildAt(0);
        mainView = getChildAt(1);
    }

    /**
     * onmesure之后调用此方法
     *
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = getMeasuredWidth();
        dragRange = 0.6f * width;
    }


    private void init() {
        floatEvaluator = new FloatEvaluator();
        intEvaluator = new IntEvaluator();

        helper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return child == menuView || child == mainView;
            }

            /**
             * 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面;
             * 最好不要返回0
             */
            @Override
            public int getViewHorizontalDragRange(View child) {
                return (int) dragRange;
            }

            /**
             * 控制child在水平方向的移动 left:
             * 表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx dx:
             * 本次child水平方向移动的距离 return: 表示你真正想让child的left变成的值
             */
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                if (child == mainView) {
                    if (left < 0) left = 0;//限制左边的边界
                    if (left > dragRange) left = (int) dragRange;//限制右边的边界
                }
                return left;
            }

            /**
             * 控制child在垂直方向的移动 top:
             * 表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy dy:
             * 本次child垂直方向移动的距离 return: 表示你真正想让child的top变成的值
             */
            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                if (changedView == menuView) {
                    //固定menuview
                    menuView.layout(0, 0, menuView.getMeasuredWidth(), menuView.getMeasuredHeight());
                    //移动主界面
                    int newLeft = mainView.getLeft() + dx;
                    if (newLeft < 0) newLeft = 0;
                    if (newLeft > dragRange) newLeft = (int) dragRange;
                    mainView.layout(newLeft, mainView.getTop() + dy, mainView.getMeasuredWidth() + newLeft, mainView.getBottom() + dy);
                }

                //计算百分比，设置动画效果
                float fraction = mainView.getLeft() / dragRange;
                excuseAnimation(fraction);

                //3.更改状态，回调listener的方法
                if (fraction == 0 && currentState != DragState.Close) {
                    currentState = DragState.Open;
                    if (listener != null) listener.onOpen();
                } else if (fraction == 1 && currentState != DragState.Open) {
                    currentState = DragState.Close;
                    if (listener != null) listener.onClose();

                }

                if (listener != null) {
                    listener.onDraging(fraction);

                }

            }

            /**
             * 当child的位置改变的时候执行,一般用来做其他子View的伴随移动 changedView：位置改变的child
             * left：child当前最新的left top: child当前最新的top dx: 本次水平移动的距离 dy: 本次垂直移动的距离
             */
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                //设置左右半边的自动滑动到界面的操作
                if (mainView.getLeft() < dragRange / 2) {
                    //在左边
                    closeMenu();
                } else {
                    //在右边
                    openMenu();
                }
                //根据滑速来操作
                if (xvel > 200&&currentState!= DragState.Open) {
                    openMenu();
                }  else if (xvel < -200 && currentState != DragState.Close) {
                    closeMenu();
                }

            }
        });
    }

    /**
     * 根据比例执行缩放动画效果
     *
     * @param fraction
     */
    private void excuseAnimation(float fraction) {
        //缩小mainView
//		float scaleValue = 0.8f+0.2f*(1-fraction);//1-0.8f

        ViewHelper.setScaleX(mainView, floatEvaluator.evaluate(fraction, 1f, 0.8f));
        ViewHelper.setScaleY(mainView, floatEvaluator.evaluate(fraction, 1f, 0.8f));
        //移动menuView
        ViewHelper.setTranslationX(menuView, intEvaluator.evaluate(fraction, -menuView.getMeasuredWidth() / 2, 0));
        //放大menuView
        ViewHelper.setScaleX(menuView, floatEvaluator.evaluate(fraction, 0.5f, 1f));
        ViewHelper.setScaleY(menuView, floatEvaluator.evaluate(fraction, 0.5f, 1f));
        //改变menuView的透明度
        ViewHelper.setAlpha(menuView, floatEvaluator.evaluate(fraction, 0.3f, 1f));

        //给SlideMenu的背景添加黑色的遮罩效果
        getBackground().setColorFilter((Integer) ColorUtil.evaluateColor(fraction, Color.BLACK, Color.TRANSPARENT), PorterDuff.Mode.SRC_OVER);
    }

    /**
     * 关闭菜单
     */
    public void closeMenu() {
        helper.smoothSlideViewTo(mainView, 0, mainView.getTop());
        //刷新
        ViewCompat.postInvalidateOnAnimation(MySlideMenu.this);
    }

    /**
     * 打开菜单
     */
    public void openMenu() {
        helper.smoothSlideViewTo(mainView, (int) dragRange, mainView.getTop());
        ViewCompat.postInvalidateOnAnimation(MySlideMenu.this);
    }

    /**
     * 此方法必须写
     */
    public void computeScroll() {
        if (helper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(MySlideMenu.this);
        }
    }

    @Override
    public boolean onInterceptHoverEvent(MotionEvent event) {
        return helper.shouldInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        helper.processTouchEvent(event);
        return true;
    }


    /******************
     * 对外的接口调用
     *********************/
    private OnDragStateChangeListener listener;

    public void setListener(OnDragStateChangeListener listener) {
        this.listener = listener;
    }

    public interface OnDragStateChangeListener {
        void onOpen();

        void onClose();

        void onDraging(float fraction);

    }

}
